package cn.tyz.kotlin.note

/**
 * @author : tyz
 * @ClassName: Note03
 * @Description:
 * @time 2018/5/22 23:59
 */

fun main(args: Array<String>) {


}


//25 接口与抽象类 ======================
fun showDemo25(args: Array<String>) {
    val computer = Computer() //新建电脑
    val mouse = LogitechMouse() //新建罗技鼠标
    computer.addInputDevice(mouse) //把鼠标添加到电脑上
}

interface InputDevice { //输入设备接口
    fun input(event: Any) //输入的方法
}
interface USBInputDevice: InputDevice //user输入设备接口
interface BLEInputDevice: InputDevice //蓝牙输入设备接口
interface OpticalMouse //光电鼠标接口
abstract class USBMouse(val name: String): USBInputDevice, OpticalMouse { //usb鼠标
    override fun input(event: Any) {

    }

    override fun toString(): String {
        return name
    }
}
class LogitechMouse : USBMouse("罗技鼠标") {

}
class Computer { //电脑类
    fun addUSBInputDevice(inputDevice: USBInputDevice) { //插入usb输入设备
        println("add usb input device: $inputDevice")
    }

    fun addBLEInputDevice(inputDevice: BLEInputDevice) { //插入蓝牙输入设备
        println("add ble input device: $inputDevice")
    }

    fun addInputDevice(inputDevice: InputDevice) { //插入输入设备
        when (inputDevice) {
            is BLEInputDevice -> {
                addBLEInputDevice(inputDevice)
            }
            is USBInputDevice -> {
                addUSBInputDevice(inputDevice)
            }
            else -> {
                throw IllegalArgumentException("输入设备类型不支持")
            }
        }
    }
}




fun showDemo26(){
    //多态，父类或已实现的接口指向子类的引用
    val a: A = E(0)
    val b: B = E(0)
    val e: E = E(0)

    if (e is A) { //表示e继承了抽象类A

    }

    if (e is B) { //表示e实现了接口B

    }
}

/**
 * 26 ======================================
 * 接口与抽象类的区别：
 * 1.抽象类可以为属性设置值和getter、setter，而接口不可以
 * 2.抽象类和接口中都可以有默认的实现方法，但接口中的方法不能有状态，
 * 即涉及到属性的值需要到实现类中设置
 * 3.子类只能继承一个父类，但可以实现多个接口
 */
abstract class A { //抽象类
    var i = 0 //抽象类的属性可以有值

//    fun hello() { //普通的方法默认为final方法，不能被子类重写
//        println(i)
//    }

    open fun bye() { //添加open关键字的方法可被子类重写
        println("Bye Bye")
    }

    abstract fun say() //抽象方法一定要被子类重写
}

interface B { //接口
    var j:Int //接口中的属性不能有具体值

    fun hello() { //接口中已经实现了的方法，子类实现后可以不重写，也可以重写
        println(j)
    }

    fun say() //未实现的方法子类必须重写
}

class C: A() { //实现抽象类，需调用父类的构造方法
    override fun say() { //抽象方法必须重写

    }

    override fun bye() { //添加open关键字的方法可以被重写，但不是必须的
        super.bye()
    }

}

class D(override var j: Int): B { //实现接口需重写参数
    override fun say() { //接口中未默认实现的方法需重写

    }
}

class E(override var j: Int) : A(), B {
    override fun say() {

    }
}


/**
 * 27 继承 =======================
 * 1.类默认是final类的，不可以继承，需要继承需要加abstract或者open关键字
 * 2.不加open关键词的方法也是final型的，不能被重写
 * 3.对于abstract关键词修饰的方法，子类必须实现，不需要使用super关键字
 * 4.如子类需要重写父类的属性，父类的属性需加open关键字，子类需加override关键字
 */
fun showExtend(){
    val person: Person = Marker(23)
    person.work()
    println(person.age)
    val person2: Person = Doctor(29)
    person2.work()
    println(person2.age)
}
abstract class Person(open val age: Int) {
    open fun work() {

    }
}

class Marker(age: Int) : Person(age) {
    override val age: Int
        get() = 0

    override fun work() {
        super.work()
        println("我是码农，在写代码")
    }
}

class Doctor(override val age: Int) : Person(age) {
    override fun work() {
        super.work()
        println("我是医生，在看病")
    }
}


// 28 接口代理=======================================
fun showInterfaceProxy() {
    val driver = CarDriver() //新建司机
    val writer = PPTWriter() //新建ppt制作者
    val seniorManager = SeniorManager(driver, writer) //新建资深经理

    seniorManager.drive() //开始驾驶
    seniorManager.write() //开始写作
}
/**
 * 1.在类的构造方法中，如不用val或者var修饰参数，
 * 该参数不为属性，只能被类内部的属性访问到，方法内访问不到
 */
interface Driver { //驾驶接口
    fun drive()
}

interface Writer { //写作接口
    fun write()
}

//资深经理，实现了驾驶和写作的接口，并带有driver和writer两个属性
class SeniorManager(val driver: Driver, val writer: Writer): Driver by driver, Writer {
//将Driver接口使用by关键字交由传入的属性driver代理之后，会自动调用driver中的driver()方法
//以下三行代码可省略
//    override fun drive() {
//        driver.drive()
//    }

    override fun write() {
        writer.write()
    }
}

class CarDriver: Driver { //小车司机，实现了驾驶接口
    override fun drive() {
        println("正在驾驶")
    }
}

class PPTWriter : Writer { //ppt制作人，实现了写作接口
    override fun write() {
        println("正在制作ppt")
    }
}

class Manager: Driver, Writer { //经理，实现了驾驶和写作的接口
    override fun drive() {

    }

    override fun write() {

    }
}



// 29 接口冲突 ======================================
fun showInterface() {
    println(I(3).x())
    println(I(-10).x())
    println(I(-120).x())
    println(I(-10000).x())
}
/**
 * 父类方法、属性需要open关键字才可以被重写
 */
interface F {
    fun x(): Int = 2
}

interface G {
    fun x(): Int = 1
}

interface H {
    fun x(): Int = 0
}

class I(var y: Int = 0): F, G, H {
    override fun x(): Int {
        if (y > 0) {
            println("call x(): Int int I")
            return y
        } else if (y < -200) {
            println("call x(): Int int F")
            return super<F>.x()
        } else if (y < -100) {
            println("call x(): Int int G")
            return super<G>.x()
        } else {
            println("call x(): Int int H")
            return super<H>.x()
        }
    }
}
/**
 * 30 访问修饰符
 * 1.类的访问修饰符有private、protected、internal、public，可见性逐步加大
 * 2.private仅本类可见
 * 3.protected本类及其子类
 * 4.internal模块内部可见
 * 5.public全局可见
 *
 * 注意点
 * 1.类的属性默认是public
 */